/* Inline Editor, for click-input editing */

function InlineEditor(params){ this.init( params );
    var self = this;
    //this.wrap = function(e){ self.listener(e); };
}

InlineEditor.prototype = {
    init:   function(params) { for(var i in params){ this[i] = params[i]; }},
    bound:  {},
    type:   "input",
    close: function(input)
    {
        this.value(input, input.value);
    },
    cancel: function(input)
    {
        this.value(input, input.getAttribute('previous'));
    },
    value: function(input, text)
    {
        var value       = typeof(this.unserialize) == 'function' ? this.unserialize(text) : text;
        var progress    = input.parentNode;
        progress.removeChild( input );
        var text        = document.createTextNode( value );
        progress.appendChild( text );
        $(progress).removeClass('editing');
    },
    listener: function(e)
    {
        var item = e.currentTarget;
        if( $(item).hasClass('editing') )
        {
            return;
        }
        else
        {
            var text        = item.innerHTML.replace(/^\s+$/, '');
            var value       = typeof(this.serialize) == 'function' ? this.serialize(text) : text;
            var input       = document.createElement(this.type);
            if( this.type != "textarea" )
            {
                input.type      = "text";
            }
            input.value     = value
            input.setAttribute("previous", value);
            
            if( typeof(this.keydown) == 'function' )
                $(input).keydown( this.keydown(this) );
            if( typeof(this.keyup) == 'function' )
                $(input).keyup( this.keyup(this) );
            
            while( item.firstChild )
                item.removeChild(item.firstChild);
            
            item.appendChild( input );
            $(item).addClass('editing');
            input.focus();
        }
    },
    bind: function(method) {
        var self = this;
        if( this.bound[method] == undefined )
            this.bound[method] = function(e){ self[method](e); };
        return this.bound[method];
    }
};


var EditorLibrary = {
    "keyup":    function(o) {
        return function(e) {
            var input = e.currentTarget;
            if( e.keyCode == 17 )
                input.removeAttribute("ctrl");
        };
    },
    "keydown":  function(o) {
        return function(e) {
            var input = e.currentTarget;
            var ctrl  = input.getAttribute("ctrl");
            
            if( e.keyCode == 17 )
            {
                input.setAttribute("ctrl", "1");
                return true;
            }
            
            if( ctrl==1 && e.keyCode == 13 )
            {
                input.value += "\n";
                return false;
            }
            
            if( e.keyCode == 13 )
            {
                o.close( input );
            }
            else if( e.keyCode == 27 )
            {
                o.cancel( input );
            }
            
            if( e.keyCode==190 || e.keyCode==191 || e.keyCode <= 57 )
            {
                return true;
            }
            
            return false;
        };
    }
}

function get_listing( node )
{
    var listing = node;
    while( listing != null && !$(listing).hasClass('listing') )
        listing = listing.parentNode;
    
    return listing;    
}

function get_listing_entity( node )
{
    var listing = get_listing( node );
        
    if( listing == null ) return null;
    
    var entity      = listing.id;
    var entity_data = entity.split('-');
    return {"type": entity_data[0], "id": entity_data[1]};
}

function get_listing_state( node )
{
    var listing = get_listing( node );
    while( listing != null && !$(listing).hasClass('liblock') )
        listing = listing.parentNode;
    
    var block   = /(\w+)$/.exec(listing.className);
    
    return block[1];
}


var library_data = [];


function hide_controls() {
    $("#controls").fadeOut('fast');
    $("#controls").unbind("click", hide_controls);
    toggle_controls($("#controls")[0]);
}

function toggle_controls(node) {
    var active = node.getAttribute("active");
    if( active )
    {
        $("#" + active).removeClass("active");
        node.removeAttribute("active");
    }
}

function shift_record( rec, state_to, state_from )
{
    var listing = rec.parentNode.removeChild(rec);
    
    delete library_data[ state_to ];
    delete library_data[ state_from ];
    
    var dest    = $("." + state_to);
    var colm    = $(".sort-title", dest);
    
    if( dest.length>0 )
    {
        dest[0].appendChild( listing );
        $(listing).fadeIn('slow');
        colm.removeClass('.asc').addClass('.desc').trigger('click');
        window.location.href = window.location.href.toString().replace(/(#.+)?$/,'#'+listing.id);
    }
    else if( confirm("Refresh window to display this change") )
    {
        window.location.href = window.location.href.toString().replace(/#.+$/,'');
    }
}

function dispatch_control( e ) {
    var item        = e.currentTarget;
    var controls    = $("#controls")[0];
    var entity      = controls.getAttribute("active");
    var entity_data = entity.split('-');
    
    if( entity )
    {
        switch( item.innerHTML )
        {
            case 'Completed':
            case 'Current':
            case 'Backlog':
            case 'Dropped':
                // set record
                // $.post("/api/library/record.json") ...

                var map     = {"Completed":"complete", "Current":"current", "Backlog":"backlog", "Dropped":"dropped"};
                var state   = map[item.innerHTML];
                var listing = $("#" + entity)[0];
                
                // do nothing
                if( $(listing.parentNode).hasClass(state) ) return;
                
                var state_from = /(\w+)$/.exec(listing.parentNode.className);
                
                $(listing).fadeOut('fast', function(){ shift_record( listing, state, state_from[1] ); } );
                
                break;
            
            case 'Remove':
                if( confirm("Remove item from library?\nThis is a permanent operation.") )
                {
                    $.ajax(
                        {
                            "url":      "/api/library/record.json",
                            "type":     "POST",
                            "data":     {"remove":1, "context_type":entity_data[0], "id":entity_data[1]},
                            "dataType": "json",
                            "success":  function(o){
                                            var listing = $("#" + entity)[0];
                                            $(listing).fadeOut('fast', function(){ listing.parentNode.removeChild(listing); });
                                        },
                            "error":  function(o){
                                            var listing = $("#" + entity)[0];
                                            $(listing).fadeOut('fast', function(){ listing.parentNode.removeChild(listing); });
                                        }
                        }
                    );
                }
                break;
            
        }
    }
    
}

function toggle_heart( e )
{
    var listing = e.currentTarget.parentNode;
    while( !$(listing).hasClass('listing') ) listing = listing.parentNode;
    
    if( $(listing).hasClass('is-fav') )
    {
        $(listing).removeClass('is-fav');
    }
    else
    {
        $(listing).addClass('is-fav');
    }
}

function active_controls( e )
{
    var listing = e.currentTarget.parentNode;
    while( listing.nodeName != 'UL' ) listing = listing.parentNode;
    listing = listing.parentNode;
    
    if( $(listing).hasClass('active') )
    {
        $(listing).removeClass('active');
        hide_controls();
    }
    else
    {
        $(listing).addClass('active');
        var pos     = $(listing).offset();
        var height  = $(listing).height();
        var width   = $(listing).width();
        
        var y       = Math.round(pos.top + height);
        var x       = Math.round(pos.left + width);

        var controls= $("#controls")[0];
        var mx      = $(controls).width();
        
        var active  = listing.id;
        
        controls.style.left = (x - mx) + "px";
        controls.style.top  = y + "px";
        
        toggle_controls(controls);
        
        $(controls).fadeIn('fast');
        
        controls.setAttribute("active", active);
    }
    
    e.stopPropagation();
}

function scrobble( e )
{
    var curr, last;
    var control     = e.currentTarget;
    var direction   = $(control).hasClass('inc') ? 1 : -1;
    var listing     = get_listing( control );
    
    if( $(listing).hasClass('scrobbling') )
        return;
    
    var entity      = get_listing_entity( listing );
    var state       = get_listing_state( listing );
    var progress    = $(".progress", $(listing));
    
    if( "-|complete|dropped|".indexOf( state )>0 )
    {
        //alert("Please move record to non-complete/dropped state.");
        return;
    }
    
    if( progress.hasClass('editing') )
        progress = $("input", progress).attr('previous');
    else
        progress = progress[0].innerHTML.replace(/^\s+$/, '');
    
    //parse progress format (##/## ... ##/?? ... ##)
    if( progress == "" )
    {
        // increment to 1
        curr = 0;
        last = false;
    }
    else
    {
        var potential   = /(\d+)(\/([0-9\?]+))/.exec(progress);
        if( potential )
        {
            curr = parseInt( potential[1] );
            last = parseInt( potential[3] ) || false;
        }
        else
        {
            curr = -1;
        }
    }
    
    // check for bad direction
    if( direction<0 && curr <1 )
        return;
    
    if( direction>0 && last && curr==last )
        return;
    
    var params = {
        "context_type": entity.type, 
        "context_id": entity.id, 
        "attribute_type": melative_attr_type(entity.type),
        "attribute_name": curr+direction
    };
    
    $(listing).addClass('scrobbling');
    
    $.ajax(
        {
            "url":      "/api/library/" + (direction>0 ? "scrobble" : "unscrobble") + ".json",
            "type":     "POST",
            "data":     params,
            "dataType": "json",
            "success":  function(o){
                            $(listing).removeClass('scrobbling');
                        },
            "error":  function(o){
                            $(listing).removeClass('scrobbling');
                        },
        }
    );
    
    progress_node = $(".progress", $(listing)).removeClass('editing');
    progress_node[0].innerHTML = params.attribute_name + (last ? "/" + last : "/??");
}

function melative_attr_type( type )
{
    if( "-|anime|adrama|tv|".indexOf(type)>0 )
    {
        return "episode";
    }
    
    if( "-|lightnovel|literature|manga|vn|".indexOf(type)>0 )
    {
        return "chapter";
    }
    
    if( type == "blog" ) return "entry";
    if( type == "periodical" ) return "issue";
    if( type == "comic" ) return "issue";
    
    return "";
}

function init()
{
  $(".sort-rating").click( sort_library(sort_by_rating_asc, sort_by_rating_desc) );
  $(".sort-progress").click( sort_library(sort_by_progress_asc, sort_by_progress_desc) );
  $(".sort-updated").click( sort_library(sort_by_updated_asc, sort_by_updated_desc) );
  $(".sort-title").click( sort_library(sort_by_title_desc, sort_by_title_asc) );
  
  lib_edit = new InlineEditor(
    {
        keyup:   EditorLibrary.keyup,
        keydown: EditorLibrary.keydown
    }
  );
  
  $(".progress").click( lib_edit.bind('listener') );
  $(".rating").click( lib_edit.bind('listener') );
  $("li.control").click( active_controls );
  $(document.body).click( hide_controls );
  
  $("li", $("#controls")).click( dispatch_control );
  $("img.fav", $("#melative-library")).click( toggle_heart );
  
  $(".inc", $("#melative-library")).attr("title", "Scrobble");
  $(".dec", $("#melative-library")).attr("title", "Unscrobble");

  $("a", $(".adjust")).click( scrobble )
}

function switch_state( e )
{
  var tab = e.currentTarget;
  var state = tab.href.replace(/.+#/,'');
  
  var active = $(".active", $(".tabs")).removeClass("active");
  
  if( active.length>0 )
    $("." + active[0].href.replace(/.+#/, '')).css("display","none");
 
  $(tab).addClass("active");
  $("." + state).css("display","block");
}

function show_record( e )
{
    var tr = e.currentTarget;
    var rec= tr.nextSibling;
    
    while( rec.nodeName != "TR" ) rec = rec.nextSibling;
    
    tr = $(tr);
    
    if( tr.hasClass("open") )
    {
        $(rec).slideUp('fast');
        tr.removeClass("open");
    }
    else
    {
        $(rec).slideDown('fast');
        tr.addClass("open");
        
        var img = $("img", $(rec));
        img[0].src = img[0].alt;
    }
}

function build_library( state )
{
    if( library_data[state] )
    {
        return library_data[state];
    }
    
    var state_data = [];
    
    var rows = $(".listing", $("ul."+state));
    
    for( var i=0; i<rows.length; i++ )
    {
        var row = {};
        row.rating = parseFloat($(".rating", $(rows[i]))[0].innerHTML) || 0;
        
        var progress = /percent\-(\d+)/.exec($(".progress", $(rows[i]))[0].className);
        row.progress = progress ? parseInt(progress[1]) : 0;
        
        var updated = /utc\-(\d+)$/.exec($("span", $(".updated", $(rows[i])))[0].className);
        row.updated = parseInt(updated[1]);
        row.listing = rows[i]
        
        var title   = $("a", $(".title", $(rows[i])))[0].innerHTML;
        row.title   = title;
        
        //var details = rows[i].nextSibling;
        //while( details.nodeName != 'UL' ) details = details.nextSibling;
        //row.details = details;
        
        state_data.push(row);
    }
    
    library_data[state] = state_data;
    
    return state_data;
}

function sort_by_rating_asc( a0, a1 )
{
    if( a0.rating > a1.rating )
        return 1;
    if( a0.rating == a1.rating )
        return 0;
    if( a0.rating < a1.rating )
        return -1;
}

function sort_by_rating_desc( a0, a1 )
{
    return sort_by_rating_asc( a1, a0 );
}

function sort_by_updated_asc( a0, a1 )
{
    if( a0.updated > a1.updated )
        return -1;
    if( a0.updated == a1.updated )
        return 0;
    if( a0.updated < a1.updated )
        return 1;
}

function sort_by_updated_desc( a0, a1 )
{
    return sort_by_updated_asc( a1, a0 );
}

function sort_by_progress_asc( a0, a1 )
{
    if( a0.progress > a1.progress )
        return -1;
    if( a0.progress == a1.progress )
        return 0;
    if( a0.progress < a1.progress )
        return 1;
}

function sort_by_progress_desc( a0, a1 )
{
    return sort_by_progress_asc( a1, a0 );
}

function sort_by_title_asc( a0, a1 )
{
    if( a0.title > a1.title )
        return -1;
    if( a0.title == a1.title )
        return 0;
    if( a0.title < a1.title )
        return 1;
}

function sort_by_title_desc( a0, a1 )
{
    return sort_by_title_asc( a1, a0 );
}

function sort_library( ascending_handler, descending_handler )
{
    return function( e )
    {
        var li = e.currentTarget;
        var ul = li.parentNode;
        var block = ul.parentNode;
        while(block.nodeName != 'UL') block = block.parentNode;
        
        
        var state = block.className.replace(/.+ (\w+)$/, '$1');
        var data = build_library( state );
        
        if( $(li).hasClass('asc') )
        {
            data.sort( descending_handler );
            $(li).removeClass('asc');
            $(li).addClass('desc');
        }
        else
        {
            data.sort( ascending_handler );
            if( $(li).hasClass('desc') )
            {
                $(li).removeClass('desc');
            }
            else
            {
                $('.asc', $(ul)).removeClass('asc');
                $('.desc', $(ul)).removeClass('desc');
            }
            
            $(li).addClass('asc');
        }
        
        for( var i in data )
        {
            var listing = block.removeChild( data[i].listing );
            //var details = block.removeChild( data[i].details );
            
            block.appendChild( listing );
            //table.appendChild( details );
        }
    }
}



$(document).ready( init );
